# cbc_mode.py —— S-AES 的 CBC 模式（16bit IV），含密文篡改演示（已修复解码异常）
import saes

def xor16(a, b): return (a ^ b) & 0xFFFF

def str_to_blocks2(s: str):
    b = s.encode("ascii", "strict")
    if len(b) % 2: b += b"\x00"
    return [((b[i]<<8)|b[i+1]) & 0xFFFF for i in range(0, len(b), 2)]

def blocks2_to_str(blocks):
    by = bytearray()
    for w in blocks:
        by += bytes([(w>>8)&0xFF, w&0xFF])
    # 去掉末尾补零
    clean = by.rstrip(b"\x00")
    try:
        # 正常情况尽量严格解码为 ASCII
        return clean.decode("ascii", "strict")
    except UnicodeDecodeError:
        # 出错时返回可见替代字符 + 原始十六进制，方便调试与截图
        replaced = clean.decode("ascii", "replace")
        return f"{replaced}  (raw hex: {clean.hex().upper()})"

def cbc_encrypt_ascii(msg: str, key16: int, iv16: int):
    blocks = str_to_blocks2(msg)
    out = []
    prev = iv16 & 0xFFFF
    for w in blocks:
        x = saes.encrypt_block16(xor16(w, prev), key16)
        out.append(x); prev = x
    return out  # 返回 16bit 列表

def cbc_decrypt_to_ascii(ct_blocks, key16: int, iv16: int):
    out = []
    prev = iv16 & 0xFFFF
    for x in ct_blocks:
        w = xor16(saes.decrypt_block16(x, key16), prev)
        out.append(w); prev = x
    return blocks2_to_str(out)

if __name__ == "__main__":
    K = 0x3A94
    IV = 0xBEEF
    msg = "attack at dawn!"
    ct = cbc_encrypt_ascii(msg, K, IV)
    print("CBC 密文（16bit十六进制列表）：", [f"{x:04X}" for x in ct])
    dec = cbc_decrypt_to_ascii(ct, K, IV)
    print("解密还原：", dec)

    # 篡改演示：改动第2个密文分组
    tampered = ct[:]
    tampered[1] ^= 0x0001  # 翻转最低位
    dec2 = cbc_decrypt_to_ascii(tampered, K, IV)
    print("篡改后解密：", dec2)  # 现在不会抛异常，会显示替代字符并给出 raw hex
